from fastapi import HTTPException
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from module_admin.entity.vo.common_vo import CrudResponseModel
from module_kylin.dao.strategy_tradebook_dao import StrategyTradebookDao
from module_kylin.entity.vo.strategy_tradebook_vo import (
    StrategyTradebookModel,
    StrategyTradebookPageQueryModel,
    DeleteStrategyTradebookModel,
)


class StrategyTradebookService:
    """
    策略交易登记簿服务层
    """

    @classmethod
    async def get_strategy_tradebook_list(cls, db: AsyncSession, query_model: StrategyTradebookPageQueryModel, 
                                         is_page: bool = False):
        """
        获取策略交易登记簿列表

        :param db: 数据库会话
        :param query_model: 查询参数
        :param is_page: 是否开启分页
        :return: 策略交易登记簿列表
        """
        try:
            # 获取策略交易登记簿列表
            strategy_tradebook_page = await StrategyTradebookDao.get_strategy_tradebook_list(db, query_model, is_page)

            return strategy_tradebook_page
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def get_strategy_tradebook_detail(cls, db: AsyncSession, tradebook_id: int):
        """
        获取策略交易登记簿详情

        :param db: 数据库会话
        :param tradebook_id: 登记簿id
        :return: 策略交易登记簿详情
        """
        try:
            # 获取策略交易登记簿详情
            strategy_tradebook_detail = await StrategyTradebookDao.get_strategy_tradebook_by_id(db, tradebook_id)

            if not strategy_tradebook_detail:
                raise HTTPException(status_code=404, detail=f"策略交易登记簿{tradebook_id}不存在")

            return strategy_tradebook_detail
        except HTTPException as e:
            raise e
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def add_strategy_tradebook(cls, db: AsyncSession, tradebook: StrategyTradebookModel):
        """
        添加策略交易登记簿

        :param db: 数据库会话
        :param tradebook: 策略交易登记簿信息
        :return: 操作结果
        """
        try:
            # 检查必填字段
            if not tradebook.name:
                raise HTTPException(status_code=400, detail="策略实例名称不能为空")
            if tradebook.price is None:
                raise HTTPException(status_code=400, detail="价格不能为空")
            if tradebook.buy is None or tradebook.sell is None or tradebook.bought is None or tradebook.sold is None:
                raise HTTPException(status_code=400, detail="委托买入、委托卖出、已经买入、已经卖出不能为空")

            # 检查策略交易登记簿是否已存在
            existing_tradebook = await StrategyTradebookDao.get_strategy_tradebook_by_info(db, tradebook)
            if existing_tradebook:
                raise HTTPException(status_code=400, detail=f"策略实例{tradebook.name}的交易记录已存在")

            # 添加策略交易登记簿
            new_tradebook = await StrategyTradebookDao.add_strategy_tradebook(db, tradebook)
            await db.commit()

            return new_tradebook
        except HTTPException as e:
            await db.rollback()
            raise e
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def update_strategy_tradebook(cls, db: AsyncSession, tradebook_id: int, tradebook: StrategyTradebookModel):
        """
        更新策略交易登记簿

        :param db: 数据库会话
        :param tradebook_id: 登记簿id
        :param tradebook: 策略交易登记簿信息
        :return: 操作结果
        """
        try:
            # 检查策略交易登记簿是否存在
            existing_tradebook = await StrategyTradebookDao.get_strategy_tradebook_by_id(db, tradebook_id)
            if not existing_tradebook:
                raise HTTPException(status_code=404, detail=f"策略交易登记簿{tradebook_id}不存在")

            # 如果更新了策略实例名称，检查是否与其他记录冲突
            if tradebook.name and tradebook.name != existing_tradebook.name:
                check_tradebook = StrategyTradebookModel(
                    name=tradebook.name
                )
                conflict_tradebook = await StrategyTradebookDao.get_strategy_tradebook_by_info(db, check_tradebook)
                if conflict_tradebook and conflict_tradebook.id != tradebook_id:
                    raise HTTPException(status_code=400, detail=f"策略实例{tradebook.name}的交易记录已存在")

            # 更新策略交易登记簿
            await StrategyTradebookDao.update_strategy_tradebook(db, tradebook_id, tradebook)
            await db.commit()

            return existing_tradebook
        except HTTPException as e:
            await db.rollback()
            raise e
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def delete_strategy_tradebook(cls, db: AsyncSession, delete_model: DeleteStrategyTradebookModel):
        """
        删除策略交易登记簿

        :param db: 数据库会话
        :param delete_model: 删除参数
        :return: 操作结果
        """
        try:
            # 检查策略交易登记簿是否存在
            for tradebook_id in delete_model.ids:
                existing_tradebook = await StrategyTradebookDao.get_strategy_tradebook_by_id(db, tradebook_id)
                if not existing_tradebook:
                    raise HTTPException(status_code=404, detail=f"策略交易登记簿{tradebook_id}不存在")

            # 批量删除策略交易登记簿
            await StrategyTradebookDao.batch_delete_strategy_tradebook(db, delete_model.ids)
            await db.commit()

            return CrudResponseModel(is_success=True, message='删除成功')
        except HTTPException as e:
            await db.rollback()
            raise e
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))